/*
 *  Rot-47 "encryption", obfuscates sensitive data so that it's not visible
 *  on accident.
 *
 * Copyright (c) 2010-2012 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#define CONNMAN_API_SUBJECT_TO_CHANGE
#include <connman/crypto.h>
#include <connman/log.h>
#include <connman/plugin.h>
#include <glib.h>
#include <string.h>

/* rot47 is defined over the alphabet ['!'..'~'] */
#define ROT_MIN '!'
#define ROT_MAX '~'
#define ROT_SIZE (ROT_MAX - ROT_MIN + 1)
#define ROT_HALF (ROT_SIZE / 2)

static char *rotate_encrypt(const char *key, const char *value);

static struct connman_crypto crypto_rot47 = {
        .name                   = "rot47",
        .priority               = CONNMAN_CRYPTO_PRIORITY_DEFAULT,
        .encrypt_keyvalue       = rotate_encrypt,
        .decrypt_keyvalue       = rotate_encrypt,
};

static char *rotate_encrypt(const char *key, const char *value)
{
        char *rv = g_strdup(value);
        gsize i, len = strlen(rv);

        for (i = 0; i < len; ++i) {
		int ch;

                if (rv[i] < ROT_MIN || rv[i] > ROT_MAX)
                        continue;

                /* Temporary storage in an int to avoid overflowing a char. */
                ch = rv[i] + ROT_HALF;
                if (ch > ROT_MAX) {
                        rv[i] = ch - ROT_SIZE;
                } else {
                        rv[i] = ch;
                }
        }

        return rv;
}

static int rotate_init(void)
{
        if (connman_crypto_register(&crypto_rot47) < 0) {
                connman_error("rot47: Failed to register plugin");
                return -1;
        }
        return 0;
}

static void rotate_finish(void)
{
        connman_crypto_unregister(&crypto_rot47);
}

CONNMAN_PLUGIN_DEFINE(crypto_rot47, "Rot47 Plugin", VERSION,
    CONNMAN_PLUGIN_PRIORITY_DEFAULT, rotate_init,
    rotate_finish)
